package reflect_learn

import (
	"fmt"
	"reflect"
)

type User struct {
	UserName string
	Password string
	Address  string
}

type Student struct {
	User User
	Name string
	Age  string
}

type Person struct {
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	Flag     bool   `json:"flag"`
}

//获取数据的类型和种类
func GetReflectType(x interface{}) {
	t := reflect.TypeOf(x)
	//特别注意：数组、切片、Map、指针等类型的变量，它们的.Name()都是返回空。
	fmt.Printf("type:%v kind:%v\n", t.Name(), t.Kind())
}

func (p *Person) GetPassword() string {
	return p.Password
}

func (p Person) Say1(msg string) {
	fmt.Println(p.UserName + msg)
}

func (p Person) Say() {
	fmt.Println(p.UserName + "说话了")
}

func (p Person) Eat(food string) {
	fmt.Println(p.UserName + "吃的是" + food)
}

func (p Person) Entertain(otherName string, food string) {
	fmt.Println(p.UserName + "请" + otherName + "吃了" + food)
}

func GetReflectValue(x interface{}) {
	v := reflect.ValueOf(x) //reflect.Value
	k := v.Kind()           //获取值得种类
	switch k {
	case reflect.Int64:
		// v.Int()从反射中获取整型的原始值，然后通过int64()强制类型转换
		fmt.Printf("type is int64, value is %d\n", int64(v.Int()))
	case reflect.Float32:
		// v.Float()从反射中获取浮点型的原始值，然后通过float32()强制类型转换
		fmt.Printf("type is float32, value is %f\n", float32(v.Float()))
	case reflect.Float64:
		// v.Float()从反射中获取浮点型的原始值，然后通过float64()强制类型转换
		fmt.Printf("type is float64, value is %f\n", float64(v.Float()))
	}
}

/**
todo Method结构
type Method struct {
	Name    string  //Name是方法名。
	PkgPath string  //方法的路径

	Type  Type  // 方法类型
	Func  Value // 以接收者为第一个参数
	Index int   // 方法索引
}

todo StructField结构
//描述结构中的单个字段。
type StructField struct {
	Name string         // 字段名称
	PkgPath string      // 字段在结构体中的路径,限定小写字母开头字段名(未报告)包路径。大写字母开头的包路径为空。
	Type      Type      // 字段本身的反射类型对象，类型为 reflect.Type，可以进一步获取字段的类型信息
	Tag       StructTag // 字段标签字符串
	Offset    uintptr   // 结构中的偏移量（字节）
	Index     []int     // Type.FieldByIndex的索引序列
	Anonymous bool      // 是否匿名字段
}


todo Type接口方法汇总
type Type interface {
    //适用于所有类型的方法。类型在内容分配时,返回的字节的对齐方式
	Align() int

	// 当类型作为一个结构的字段时,他的字节对齐方式
	FieldAlign() int

    // 方法返回类型的方法集中的第i个方法。
    // 如果我不在[0，NumMethod()]范围内，它会报错。
    // 对于非接口类型T或*T，返回的方法的类型和函数
    // 字段描述第一个参数是接收器的函数。
    // 对于接口类型，返回方法的type字段提供者
	// 通过整形索引,反射类型的方法,返回一个Method类型
	Method(int) Method

	// 通过方法名,判断该类型是否有该方法,如果存在返回该方法,并且返回ok值为true
	MethodByName(string) (Method, bool)

	// 返回该类型拥有的外部可调用的方法数量（方法名称为英文字母大写开头的）
	NumMethod() int

	// 返回类型的名称,如果是匿名类型将返回空字符窜。
    // 如果是数组、切片、Map、指针等类型,则什么都没有
	Name() string

	//返回类型所在包的路径,如果是指针则什么都木有
	PkgPath() string

	// 返回存储所需的字节数
	// 给定类型的值；类似于unsafe.Sizeof。
	Size() uintptr

	// 返回该类型的字符串表示形式。
    //字符串表示可以使用缩短的包名称（例如，base64而不是"encoding/base64"）
	String() string

	// 返回这个类型的种类,(比如struct,slice,ptr,func等)
	Kind() Kind

	// 判断类型是否实现u这个接口.注意u必须不能为nil,且是一个接口
	Implements(u Type) bool

	// 判断类型是否可分配到u类型
	AssignableTo(u Type) bool

	// 判断该类型的值是否可以转换为u类型
	ConvertibleTo(u Type) bool

	// 判断此类型的值是否可比较。
	Comparable() bool

    //方法仅适用于某些类型，具体取决于类型
    //每种方法都允许：
	//
	//	Int*, Uint*, Float*, Complex*: Bits
	//	Array: Elem, Len
	//	Chan: ChanDir, Elem
	//	Func: In, NumIn, Out, NumOut, IsVariadic.
	//	Map: Key, Elem
	//	Ptr: Elem
	//	Slice: Elem
	//	Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
    //返回反射类型的使用的大小（以位为单位）,如果不是Int,Uint,Float,complex种类则会产生恐慌
	Bits() int

	// 返回反射channel的目录，如果该类型不是chan则会出现异常
	ChanDir() ChanDir

	// 判断函数是否有可变参数(...)
	IsVariadic() bool

    //Elem返回类型的元素类型。
    //如果类型的类型不是Array、Chan、Map、Ptr或Slice，则会出现恐慌。
	Elem() Type

	//返回结构类型的第i个字段。值为StructField类型
    //如果类型的类型不是Struct，它就会恐慌。
    //如果不在[0，NumField（）]范围内，它会惊慌失措。
	Field(i int) StructField

	// 返回对应的嵌套字段
    //如果类型的类型不是Struct，它就会恐慌。
	FieldByIndex(index []int) StructField

    //FieldByName返回具有给定名称的结构字段
    //以及一个布尔值，指示是否找到该字段。
	FieldByName(name string) (StructField, bool)

	//FieldByNameFunc返回具有名称的结构字段,以及一个布尔值，指示是否找到该字段
    //FieldByNameFunc考虑结构本身中的字段,然后是任何嵌入结构中的字段，以宽度优先的顺序，
    //停在最浅的嵌套深度，包含一个或多个,满足匹配函数的字段。
	FieldByNameFunc(match func(string) bool) (StructField, bool)

    //返回函数类型的第i个输入参数的类型。
    //如果类型的类型不是Func，它就会恐慌。
    //如果我不在[0，NumIn()]范围内，它会惊慌失措。
	In(i int) Type

    // 反射map类型的key的类型,如果不是map则会产生恐慌
	Key() Type

	// 返回反射array类型的长度,如果不是array,则会产生恐慌
	Len() int

	// 返回反射一个struct的字段数量,如果不是struct则会产生恐慌
	NumField() int

	// 反射一个func的输入参数的数量,如果不是函数则会产生恐慌
	NumIn() int

	//NumOut返回函数类型的输出参数计数。
    //如果类型的类型不是Func，它就会恐慌。
	NumOut() int

	//Out返回函数类型的第i个输出参数的类型。
    //如果类型的类型不是Func，它就会恐慌。
    //如果我不在[0，NumOut（）范围内，它会惊慌失措。
	Out(i int) Type

    //返回*rtype结构，该指针是大多数值的常见实现。
    //它嵌入到其他结构类型中。
	common() *rtype

    //返回*uncommonType类型，该类型只存在于定义的类型或具有方法的类型
    //（如果T是定义的类型，则T和*T的unmontypes有方法）。
    //使用指向此结构的指针可以减少所需的总体大小
    //描述没有方法的未定义类型。
	uncommon() *uncommonType
}



todo reflect.Kind

//Kind代表具体的特定类型。
//Invalid不是有效类型。
type Kind uint
const (
    Invalid Kind = iota  // 非法类型
    Bool                 // 布尔型
    Int                  // 有符号整型
    Int8                 // 有符号8位整型
    Int16                // 有符号16位整型
    Int32                // 有符号32位整型
    Int64                // 有符号64位整型
    Uint                 // 无符号整型
    Uint8                // 无符号8位整型
    Uint16               // 无符号16位整型
    Uint32               // 无符号32位整型
    Uint64               // 无符号64位整型
    Uintptr              // 指针
    Float32              // 单精度浮点数
    Float64              // 双精度浮点数
    Complex64            // 64位复数类型
    Complex128           // 128位复数类型
    Array                // 数组
    Chan                 // 通道
    Func                 // 函数
    Interface            // 接口
    Map                  // 映射
    Ptr                  // 指针
    Slice                // 切片
    String               // 字符串
    Struct               // 结构体
    UnsafePointer        // 底层指针
)



todo Value结构体的方法
//通常用于获取一个指向结构体字段或slice元素,为了调用一个方法,需要一个指针接收。
func (v Value) Addr() Value

//返回底层的值,如果v的kind不是bool则会产生恐慌
func (v Value) Bool() bool

//返回底层的值,如果v的底层值不是一个字节切片,则会产生恐慌
func (v Value) Bytes() []byte

//检查v是否是可寻址的
func (v Value) CanAddr() bool

// 检查值是否可被设置,只有可寻址的才能被设置
func (v Value) CanSet() bool

// 反射函数的值.并调用
func (v Value) Call(in []Value) []Value

//同Call
func (v Value) CallSlice(in []Value) []Value

//关闭channel,如果不是chan则产生恐慌
func (v Value) Close()

//返回底层的值,如果值不是一个复数,则产生一个恐慌
func (v Value) Complex() complex128

//返回v包含的值,多被用于设置值时的寻址操作
func (v Value) Elem() Value

//返回结构中索引字段的Value
func (v Value) Field(i int) Value

//同上不过.提供的是一个切片
func (v Value) FieldByIndex(index []int) Value

//通过字段名查找结构中的值
func (v Value) FieldByName(name string) Value

//通过函数名查找
func (v Value) FieldByNameFunc(match func(string) bool) Value

//返回底层的值,如果值不是一个float,则产生一个恐慌
func (v Value) Float() float64

//如果kind不是array或者sliece则产生恐慌,将其中的元素返回为Value
func (v Value) Index(i int) Value

//返回底层的值,如果值不是一个int,则产生一个恐慌
func (v Value) Int() int64

//如果接口能被使用,则返回true
func (v Value) CanInterface() bool

//返回V作为interface{}的当前值
func (v Value) Interface() (i interface{})

//如果kind不是一个接口则会产生恐慌
func (v Value) InterfaceData() [2]uintptr

//返回值是否为 nil。如果值类型不是通道（channel）、函数、接口、map、指针或 切片时发生 panic，类似于语言层的v== nil操作
func (v Value) IsNil() bool

//判断值是否有效。当值本身非法时,返回false，例如reflect Value不包含任何值,值为 nil 等。
func (v Value) IsValid() bool

//返回v的种类
func (v Value) Kind() Kind

//返回v的长度
func (v Value) Len() int

//如果是一个map,根据key反射其键值的Value
func (v Value) MapIndex(key Value) Value

//返回map的所有key
func (v Value) MapKeys() []Value

//按索引反射结构某个方法的值
func (v Value) Method(i int) Value

//统计结构方法数量
func (v Value) NumMethod() int

//反射方法的值根据方法名
func (v Value) MethodByName(name string) Value

//反射一个结构的字段数
func (v Value) NumField() int

//覆盖复数
func (v Value) OverflowComplex(x complex128) bool

//覆盖浮点数
func (v Value) OverflowFloat(x float64) bool
func (v Value) overflowFloat32(x float64) bool
func (v Value) OverflowInt(x int64) bool
func (v Value) OverflowUint(x uint64) bool

//反射一个指针的值.返回一个指针的整型值
func (v Value) Pointer() uintptr

//用于channel接收
func (v Value) Recv() (x Value, ok bool)

//用于channel发送
func (v Value) Send(x Value)

//如果v可设置,则设置一个v的值
func (v Value) Set(x Value)

//如果v可设置,且是bool,则设置一个v的值
func (v Value) SetBool(x bool)
func (v Value) SetBytes(x []byte)
func (v Value) SetComplex(x complex128)
func (v Value) SetFloat(x float64)
func (v Value) SetInt(x int64)
func (v Value) SetLen(n int)
func (v Value) SetMapIndex(key, val Value)
func (v Value) SetUint(x uint64)
func (v Value) SetPointer(x unsafe.Pointer)
func (v Value) SetString(x string)
func (v Value) Slice(beg, end int) Value

//如果底层是slice.则返回值.
func (v Value) String() string

//如果底层是字符串.则返回字符串
func (v Value) TryRecv() (x Value, ok bool)

//用于channel,接受
func (v Value) TrySend(x Value) bool

//用于channel,发送
func (v Value) Type() Type

//返回type
func (v Value) Uint() uint64

//如果底层是Uint.则返回uint
func (v Value) UnsafeAddr() uintptr


*/
